package me.fanwu.GatewayDemo;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.gateway.filter.ratelimit.KeyResolver;
import org.springframework.cloud.gateway.filter.ratelimit.RedisRateLimiter;
import org.springframework.cloud.gateway.route.RouteLocator;
import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.data.redis.connection.ReactiveRedisConnectionFactory;
import org.springframework.data.redis.core.ReactiveStringRedisTemplate;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Mono;

@RestController
@SuppressWarnings("HttpUrlsUsage")
@SpringBootApplication
public class GatewayDemoApplication {

    @Autowired
    private ReactiveRedisConnectionFactory connectionFactory;

    @Bean
    public RouteLocator getRoutes(RouteLocatorBuilder routeLocatorBuilder) {
        return routeLocatorBuilder.routes()
                .route("modify_body", r -> r.path("/manager_dataload/**")
                        .filters(f ->
                                f.modifyRequestBody(String.class, String.class, MediaType.APPLICATION_JSON_VALUE,
                                        (exchange, body) -> {
                                            return Mono.just(addJsonSign(body));
                                        })
                                        //since this is a slow request, the request will be redirected to fall_back
                                        .circuitBreaker(c -> c.setName("slow_req").setFallbackUri("forward:/fall_back"))
                        ).uri("http://managerapp-test.ktvme.com/"))

                .route("limit_route", r -> r.path("/mgr_upload/**").filters(f ->
                        f.addRequestHeader("hello", "world")
                        .requestRateLimiter(c -> c.setRateLimiter(redisRateLimiter()))
                ).uri("http://192.168.99.10:3056/"))

                .build();
    }

    @Bean
    public RedisRateLimiter redisRateLimiter() {
        return new RedisRateLimiter(1, 2);
    }

    @Bean
    public KeyResolver userKeyResolver() {
        return exchange -> Mono.just("1");
    }

    @Bean
    public ReactiveStringRedisTemplate reactiveStringRedisTemplate() {
        return new ReactiveStringRedisTemplate(connectionFactory);
    }

    @RequestMapping("/fall_back")
    public String fallBack() {
        return "{\"ret\":6662004,\"msg\":\"too slow to fall back\"}";
    }

    public static void main(String[] args) {
        SpringApplication.run(GatewayDemoApplication.class, args);
    }

    /**
     * fake func to add sign data field upon original inputJson     *
     */
    private static String addJsonSign(String inputJson) {
        return "{\n" +
                "  \"companyCode\": \"08204\",\n" +
                "  \"title\": \"哈哈哈哈\",\n" +
                "  \"message\": \"有大魔王出世！!!\",\n" +
                "  \"url\": \"http://www.baidu.com\",\n" +
                "  \"sign\": \"A11388299DF24B6BF13F3A217C8042C8\"\n" +
                "}";
    }
}
